package com.skype.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.net.InetSocketAddress;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.util.Iterator;
import java.util.Set;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.swing.KeyStroke;

import com.skype.Application;
import com.skype.ApplicationAdapter;
import com.skype.Friend;
import com.skype.Skype;
import com.skype.SkypeException;
import com.skype.Stream;
import com.skype.StreamAdapter;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

/**
 * 本class的作用是实现一个简易的Http服务器， 监听来自Firefox发送的对话框坐标和message等信息，然后强制把信息模拟发送给FF
 * 
 * @author Administrator
 * 
 */
public class SkypeHttpLisener {
	private int port;
	private java.util.Timer timer = null;
    private static String[] str=new String[378];
	private static  final AtomicInteger msgNum=new AtomicInteger(0);
	private static Stream stream=null; //专门用于发送信息！
	private static  final EncrypRSA rsa = new EncrypRSA();
	//保存全部加密key，因为可能和不同的skype用户通讯！
	private static final ConcurrentHashMap<String,RSAPublicKey> keyMap=new ConcurrentHashMap<String,RSAPublicKey>();
	private static final ConcurrentHashMap<String,Stream> streamMap=new ConcurrentHashMap<String,Stream>();
	private static final ContactService service=ContactService.getInstance();
	
	public SkypeHttpLisener() {
	}

	public SkypeHttpLisener(int port) {
		this.port = port;
		try {
			skypeConnect();
		} catch (SkypeException e) {
			e.printStackTrace();
		}
	}
	
	public void sendEncryptedMessageToFriend(String msg) throws SkypeException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{
		String focused=service.getFocusedContact();
		if(focused!=null){
			Stream stream=	streamMap.get(focused);
			RSAPublicKey publicKey=keyMap.get(focused);
			byte[] encrypted=rsa.encrypt(publicKey, msg.getBytes());
			System.out.println("Send Message is: "+new String(encrypted));
			stream.write(new String(encrypted));
		}
	}
	
    private void skypeConnect() throws SkypeException{
        Skype.setDebug(true);//必须=true，否则无法获取focused联系人！
        Skype.setDeamon(false);
        Application application = Skype.addApplication(AP2APTest.class.getName());
        application.addApplicationListener(new ApplicationAdapter() {
       //当有相同的应用与此应用连接时，此方法将被调用
       //如果其它同修运行此程序，本事件触发！
            public void connected(Stream stream) throws SkypeException {
            	SkypeHttpLisener.this.stream=stream;
            	String myPublicKey=rsa.toPublicKey();
            	
                
                Friend frd=stream.getFriend();
                
                final String friend=frd.getId();
                Object streamLocal=	streamMap.get(friend);
                if(streamLocal==null){//说明这个用户才上线，需要保存！
                	streamMap.put(friend, stream);
                }
            	SkypeHttpLisener.this.streamMap.put(friend, stream);//把连接Stream放到HashMap中
                System.out.println("connected:" + stream.getId()+" friend:"+friend);
                stream.addStreamListener(new StreamAdapter() {
                    @Override
                    public void textReceived(String receivedText) throws SkypeException {
                    //处理接收到的文本消息！
                    	try {
                    		System.out.println("receivedText received:" + receivedText);
                    		if(receivedText.equals("keyRequest")){
                    			Stream stream=streamMap.get(friend);
                        		String myPublicKey=rsa.toPublicKey();
                        		stream.send(myPublicKey);
                    		}else if(keyMap.get(friend)!=null){
    							          byte[] decBytes = rsa.decrypt(receivedText.getBytes());//执行消息解密
    	                    	System.out.println("decrypt is: "+new String(decBytes));
                    		}
						} catch (Exception e) {
							e.printStackTrace();
						} 
                    }
                    //把我自己的加密key广播给全部运行加密程序的同修！
                    public void datagramReceived(String receivedDatagram) throws SkypeException {
                    	System.out.println("receivedDatagram received:" +friend+ receivedDatagram);
                     	//用户的key是否已经保存，如果没有，说明对方也没有我们的key！
                    	Object savedKey=SkypeHttpLisener.this.keyMap.get(friend);
                    	Stream stream=streamMap.get(friend);
                    	if(savedKey==null){//说明改用户还没有得到我们的key
                    		String myPublicKey=rsa.toPublicKey();
                    		stream.send(myPublicKey);
                    	}
                   	    RSAPublicKey eyncrptKey=rsa.fromPublicKey(receivedDatagram);
                    	SkypeHttpLisener.this.keyMap.put(friend, eyncrptKey);//把来自新Friend的公钥加入到List中1
                    }
                });
            }
        });
	       //完成向所有联系人的请求连接，此方法返回Stream数组 
        String publicKey=rsa.toPublicKey();
        System.out.println("publicKey:"+publicKey);
	    Stream[] streams=application.connectToAll();
	       //向每一个注册了相同应用的SKYPE实例发送文本消息，也是基于SKYPE开发应用的入口点之一
	    for(Stream stream: streams) {
	       if(stream != null) {
	    	   String friend=stream.getFriend().getId();
	    	   System.out.println("Friend's name is: "+friend);
           	  //streamMap.put(friend, stream);//把连接Stream放到HashMap中
	    	  //stream.send(publicKey);
	          stream.write("keyRequest");//请求其它用户的Public Key
	          System.out.println("stream.getFriend().getDisplayName():"+stream.getFriend().getId());
	       }
	    }
       
    }
     
   	public void start() {
		try {
		    InetSocketAddress address = new InetSocketAddress("127.0.0.1", port);
			HttpServer server = HttpServer.create(address, 0);
			
			server.createContext("/", new HttpHandler() {
				public void handle(HttpExchange he) {
					try {
						sendEncryptedMessageToFriend("hello world!");
						String ip = he.getRemoteAddress().getAddress().getHostAddress();
						//System.out.println("http消息发送的来源ip是："+ip);
						InputStream input_stream = he.getRequestBody();
						Headers paramHeaders = he.getRequestHeaders();
						Iterator params = paramHeaders.keySet().iterator();
						while (params.hasNext()) {
							String key = (String) params.next();
							String value = paramHeaders.getFirst(key);
							//System.out.println("Key  = " + key + "--- Value = "+ value);
						}
						BufferedReader reader = new BufferedReader(
								new InputStreamReader(input_stream));
						StringBuilder str_builder = new StringBuilder();

						String line = null;
						while ((line = reader.readLine()) != null) {
							str_builder.append(line + "\n");
						}
						String qStr=str_builder.toString();
						//System.out.println("send parameters string is:  "+ qStr);
						QueryString qs = new QueryString(qStr);
						if(qStr.contains("msg")){
						   handleMsg(qs);
						}else if(qStr.contains("method=logout")){
						   //handleLogout(qs);
						}else if(qStr.contains("method=login")){
						   //handleLogin(qs);
						}
						// 登录，
						String ret = "OK";
						he.sendResponseHeaders(200,ret.getBytes("utf-8").length);
						OutputStream os = he.getResponseBody();
						os.write(ret.getBytes());
						os.close();
					} catch (Exception e) {
						System.out.println("handle Exception");
						e.printStackTrace();
					}

				}

				/**
				 * @param qs
				 */
				private void handleMsg(QueryString qs) {
					String msg = qs.getParameter("msg");
				}
				
			});
			server.start();
			System.out.println("Monitoring " + port + " port");
		} catch (Exception e) {
			System.out.println("localHttpLisener Exception");
			//e.printStackTrace();
		}

	}

	public static void main(String[] args) throws Exception {
		
		new SkypeHttpLisener(19988).start();
	}

}
